


Here's a list of all the types that can be represented in BAML:

## Primitive Types
* `bool`
* `int`
* `float`
* `string`
* `null`

## Literal Types
<Info>
  This feature was added in: v0.61.0.
</Info>

The primitive types `string`, `int` and `bool` can be constrained to a specific value.
For example, you can use literal values as return types:

```rust
function ClassifyIssue(issue_description: string) -> "bug" | "enhancement" {
  client GPT4Turbo
  prompt #"
    Classify the issue based on the following description:
    {{ ctx.output_format }}

    {{ _.role("user")}}
    {{ issue_description }}
  "#
}
```

See [Union(|)](#union-) for more details.


## Multimodal Types
See [calling a function with multimodal types](/guide/baml-basics/multi-modal)
and [testing image inputs](/guide/baml-basics/testing-functions#test-image-inputs-in-the-playground)

<Accordion title="Implementation details: runtime and security considerations">
  BAML's multimodal types are designed for ease of use: we have deliberately made it
  easy for you to construct an `image`, `audio`, `pdf`, or `video` instance from a URL. Under the
  hood, depending on the model you're using, BAML may need to download the file
  and transcode it (usually as base64) for the model to consume.

  This ease-of-use does come with some tradeoffs; namely, if you construct
  a multimodal instance using untrusted user input, you may be exposing
  yourself to [server-side request forgery (SSRF) attacks][ssrf]. Attackers may be
  able to fetch files on your internal network, on external networks using your
  application's identity, or simply excessively drive up your cloud network
  bandwidth bill.

  To prevent this, we recommend only using URLs from trusted sources/users or
  validating them using allowlists or denylists.

[ssrf]: https://portswigger.net/web-security/ssrf
</Accordion>

### `image`

You can use an image like this for models that support them:

```rust
function DescribeImage(myImg: image) -> string {
  client GPT4Turbo
  prompt #"
    {{ _.role("user")}}
    Describe the image in four words:
    {{ myImg }}
  "#
}
```

You cannot name a variable `image` at the moment as it is a reserved keyword.

Calling a function with an image type:

<CodeBlocks>
```python Python
from baml_py import Image
from baml_client import b

async def test_image_input():
  # from URL
  res = await b.TestImageInput(
    img=Image.from_url("https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png")
  )

  # Base64 image
  image_b64 = "iVBORw0K...."
  res = await b.TestImageInput(
    img=Image.from_base64("image/png", image_b64)
  )
```

```typescript TypeScript
import { b } from '../baml_client'
import { Image } from "@boundaryml/baml"
...

  // URL
  let res = await b.TestImageInput(
    Image.fromUrl('https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png'),
  )

  // Base64
  let res = await b.TestImageInput(
    Image.fromBase64('image/png', image_b64),
  )
```

```ruby Ruby
require_relative "baml_client/client"

b = Baml.Client
Image = Baml::Image

def test_image_input
  # from URL
  res = b.TestImageInput(
    img: Image.from_url("https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png")
  )

  # Base64 image
  image_b64 = "iVBORw0K...."
  res = b.TestImageInput(
    img: Image.from_base64("image/png", image_b64)
  )
end
```

```go Go
package main

import (
	"context"
	"log"

	b "example.com/myproject/baml_client"
)

func main() {
	ctx := context.Background()
	
	// From URL
	img, err := b.NewImageFromUrl("https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png", nil)
	if err != nil {
		log.Fatal(err)
	}
	
	res, err := b.TestImageInput(ctx, img)
	if err != nil {
		log.Fatal(err)
	}
	
	// Base64 image  
	imageB64 := "iVBORw0K...."
	img2, err := b.NewImageFromBase64(imageB64, stringPtr("image/png"))
	if err != nil {
		log.Fatal(err)
	}
	
	res2, err := b.TestImageInput(ctx, img2)
	if err != nil {
		log.Fatal(err)
	}
}

// Helper function for creating string pointers
func stringPtr(s string) *string { return &s }
```
</CodeBlocks>

<Accordion title="Pydantic compatibility">
If using Pydantic, the following are valid ways to construct the `Image` type.

```json
{
  "url": "https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png"
}
```

```json
{
  "url": "https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png",
  "media_type": "image/png"
}
```

```json
{
  "base64": "iVBORw0K....",
}
```

```json
{
  "base64": "iVBORw0K....",
  "media_type": "image/png"
}
```
</Accordion>

### `audio`

Example
```rust
function DescribeSound(myAudio: audio) -> string {
  client GPT4Turbo
  prompt #"
    {{ _.role("user")}}
    Describe the audio in four words:
    {{ myAudio }}
  "#
}
```
Calling functions that have `audio` types.

<CodeBlocks>
```python Python
from baml_py import Audio
from baml_client import b

async def run():
  # from URL
  res = await b.TestAudioInput(
      audio=Audio.from_url(
          "https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg"
      )
  )

  # Base64
  b64 = "iVBORw0K...."
  res = await b.TestAudioInput(
    audio=Audio.from_base64("audio/ogg", b64)
  )
```

```typescript TypeScript
import { b } from '../baml_client'
import { Audio } from "@boundaryml/baml"
...

  // URL
  let res = await b.TestAudioInput(
    Audio.fromUrl('https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg'),
  )

  // Base64
  const audio_base64 = ".."
  let res = await b.TestAudioInput(
    Audio.fromBase64('audio/ogg', audio_base64),
  )
  
```

```ruby Ruby
require_relative "baml_client/client"

b = Baml.Client
Audio = Baml::Audio

def test_audio_input
  # from URL
  res = b.TestAudioInput(
      audio: Audio.from_url(
          "https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg"
      )
  )

  # Base64 image
  audio_b64 = "iVBORw0K...."
  res = b.TestAudioInput(
    audio: Audio.from_base64("audio/mp3", audio_b64)
  )
end
```

```go Go
package main

import (
	"context"
	"log"

	b "example.com/myproject/baml_client"
)

func main() {
	ctx := context.Background()
	
	// From URL
	aud, err := b.NewAudioFromUrl("https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg", nil)
	if err != nil {
		log.Fatal(err)
	}
	
	res, err := b.TestAudioInput(ctx, aud)
	if err != nil {
		log.Fatal(err)
	}
	
	// Base64 audio
	audioB64 := "iVBORw0K...."
	aud2, err := b.NewAudioFromBase64(audioB64, stringPtr("audio/mp3"))
	if err != nil {
		log.Fatal(err)
	}
	
	res2, err := b.TestAudioInput(ctx, aud2)
	if err != nil {
		log.Fatal(err)
	}
}

// Helper function for creating string pointers
func stringPtr(s string) *string { return &s }
```
</CodeBlocks>

### `pdf`

Example
```rust
function AnalyzePdf(myPdf: pdf) -> string {
  client GPT4Turbo
  prompt #"
    {{ _.role("user")}}
    Summarize the main points of this Pdf:
    {{ myPdf }}
  "#
}
```
> **Note** Pdf inputs must be provided as Base64 data using `Pdf.from_base64`. URL-based inputs are not currently supported.

<CodeBlocks>
```python Python
from baml_py import Pdf
from baml_client import b

async def run():
  # Base64 data
  b64 = "JVBERi0K...."
  res = await b.TestPdfInput(
    pdf=Pdf.from_base64("application/pdf", b64)
  )
```

```typescript TypeScript
import { b } from '../baml_client'
import { Pdf } from "@boundaryml/baml"
...

  // Base64
  const pdf_base64 = ".."
  let res = await b.TestPdfInput(
    Pdf.fromBase64('application/pdf', pdf_base64),
  )
  
```

```ruby Ruby
# Pdf inputs must be provided as Base64. URL support is currently unavailable.
require_relative "baml_client/client"

b = Baml.Client
Pdf = Baml::Pdf

def test_pdf_input
  # Base64 Pdf
  pdf_b64 = "JVBERi0K...."
  res = b.TestPdfInput(
    pdf: Pdf.from_base64("application/pdf", pdf_b64)
  )
end
```

```go Go
package main

import (
	"context"
	"log"

	b "example.com/myproject/baml_client"
)

func main() {
	ctx := context.Background()
	
	// Base64 PDF (URL support is not currently available)
	pdfB64 := "JVBERi0K...."
	pdf, err := b.NewPDFFromBase64(pdfB64, stringPtr("application/pdf"))
	if err != nil {
		log.Fatal(err)
	}
	
	res, err := b.TestPdfInput(ctx, pdf)
	if err != nil {
		log.Fatal(err)
	}
}

// Helper function for creating string pointers
func stringPtr(s string) *string { return &s }
```
</CodeBlocks>

### `video`

Example
```rust
function DescribeVideo(myVideo: video) -> string {
  client GPT4Turbo
  prompt #"
    {{ _.role("user")}}
    Describe what happens in this video:
    {{ myVideo }}
  "#
}
```
Calling functions that have `video` types.

> **Note** When you provide a `Video` via URL the URL is passed directly to the model. Some models cannot download external media; in that case convert the video to Base64 first.

<CodeBlocks>
```python Python
from baml_py import Video
from baml_client import b

async def run():
  # from URL
  res = await b.TestVideoInput(
      video=Video.from_url(
          "https://example.com/sample.mp4"
      )
  )

  # Base64
  b64 = "AAAAGGZ0eXBpc29t...."
  res = await b.TestVideoInput(
    video=Video.from_base64("video/mp4", b64)
  )
```

```typescript TypeScript
import { b } from '../baml_client'
import { Video } from "@boundaryml/baml"
...

  // URL
  let res = await b.TestVideoInput(
    Video.fromUrl('https://example.com/sample.mp4'),
  )

  // Base64
  const video_base64 = ".."
  let res = await b.TestVideoInput(
    Video.fromBase64('video/mp4', video_base64),
  )
  
```

```ruby Ruby
require_relative "baml_client/client"

b = Baml.Client
Video = Baml::Video

def test_video_input
  # from URL
  res = b.TestVideoInput(
      video: Video.from_url(
          "https://example.com/sample.mp4"
      )
  )

  # Base64 video
  video_b64 = "AAAAGGZ0eXBpc29t...."
  res = b.TestVideoInput(
    video: Video.from_base64("video/mp4", video_b64)
  )
end
```

```go Go
package main

import (
	"context"
	"log"

	b "example.com/myproject/baml_client"
)

func main() {
	ctx := context.Background()
	
	// From URL
	vid, err := b.NewVideoFromUrl("https://example.com/sample.mp4", nil)
	if err != nil {
		log.Fatal(err)
	}
	
	res, err := b.TestVideoInput(ctx, vid)
	if err != nil {
		log.Fatal(err)
	}
	
	// Base64 video
	videoB64 := "AAAAGGZ0eXBpc29t...."
	vid2, err := b.NewVideoFromBase64(videoB64, stringPtr("video/mp4"))
	if err != nil {
		log.Fatal(err)
	}
	
	res2, err := b.TestVideoInput(ctx, vid2)
	if err != nil {
		log.Fatal(err)
	}
}

// Helper function for creating string pointers
func stringPtr(s string) *string { return &s }
```
</CodeBlocks>

## Composite/Structured Types

### enum

**See also:** [Enum](/docs/snippets/enum)

A user-defined type consisting of a set of named constants.
Use it when you need a model to choose from a known set of values, like in classification problems

```baml
enum Name {
  Value1
  Value2 @description("My optional description annotation")
}
```

If you need to add new variants, because they need to be loaded from a file or fetched dynamically
from a database, you can do this with [Dynamic Types](/guide/baml-advanced/dynamic-runtime-types).

### class

**See also:** [Class](/docs/snippets/class)

Classes are for user-defined complex data structures.

Use when you need an LLM to call another function (e.g. OpenAI's function calling), you can model the function's parameters as a class. You can also get models to return complex structured data by using a class.

**Example:**

Note that properties have no `:`
```baml
class Car {
  model string
  year int @description("Year of manufacture")
}
```

If you need to add fields to a class because some properties of your class are only
known at runtime, you can do this with [Dynamic Types](/docs/calling-baml/dynamic-types).

### Optional (?)

A type that represents a value that might or might not be present.

Useful when a variable might not have a value and you want to explicitly handle its absence.

**Syntax:** `Type?`

**Example:** `int?` or `(MyClass | int)?`

### Union (|)

A type that can hold one of several specified types.

This can be helpful with **function calling**, where you want to return different types of data depending on which function should be called.

**Syntax:** `Type1 | Type2`

**Example:** `int | string` or `(int | string) | MyClass` or `string | MyClass | int[]`

<Warning>
  Order is important. `int | string` is not the same as `string | int`.

  For example, if you have a `"1"` string, it will be parsed as an `int` if
  you use `int | string`, but as a `string` if you use `string | int`.
</Warning>

### List/Array ([])

A collection of elements of the same type.

**Syntax:** `Type[]`

**Example:** `string[]` or `(int | string)[]` or `int[][]`

<Tip>
  * Array types can be nested to create multi-dimensional arrays
  * An array type cannot be optional
</Tip>

### Map

A mapping of strings or enums to elements of another type.

**Syntax**: `map<string, ValueType>`

**Example**: `map<string, string>`

Enums and literal strings can also be used as keys.

```baml
enum Category {
  A
  B
  C
}

// Enum key syntax
map<Category, string>

// Literal strings syntax
map<"A" | "B" | "C", string>
```

{/* <Info>
  For TS users: `map<string, ValueType>` will generate a 
  `Record<string, ValueType>` type annotation, but using any other type for the
  key will generate a `Map`, e.g. `map<int, string>` in BAML will generate a
  `Map<number, string>` type annotation in TypeScript.
</Info> */}

### ❌ Set

- Not yet supported. Use a `List` instead.

### ❌ Tuple

- Not yet supported. Use a `class` instead.

## Type Aliases

<Info>
  This feature was added in: v0.71.0.
</Info>

A _type alias_ is an alternative name for an existing type. It can be used to
simplify complex types or to give a more descriptive name to a type. Type
aliases are defined using the `type` keyword:

```baml
type Graph = map<string, string[]>
```

Type aliases can point to other aliases:

```baml
type DataStructure = string[] | Graph
```

Recursive type aliases are supported only through map or list containers, just
like in TypeScript:

```baml
type JsonValue = int | string | bool | float | JsonObject | JsonArray
type JsonObject = map<string, JsonValue>
type JsonArray = JsonValue[]
```

Aliases can also refer to themselves:

```baml
type JsonValue = int | float | bool | string | null | JsonValue[] | map<string, JsonValue> 
```

However, this is invalid since no value can satisfy this type:

```baml
type A = B
type B = A
```

## Examples and Equivalents

Here are some examples and what their equivalents are in different languages.

### Example 1

<CodeBlocks>
```baml BAML
int? | string[] | MyClass
````

```python Python Equivalent
Union[Optional[int], List[str], MyClass]
```

```typescript TypeScript Equivalent
(number | null) | string[] | MyClass
```

```go Go Equivalent
Union3IntOrStringArrayOrMyClass // Generated union type
```

</CodeBlocks>

### Example 2

<CodeBlocks>
```baml BAML
string[]
```

```python Python Equivalent
List[str]
```

```typescript TypeScript Equivalent
string[]
```

```go Go Equivalent
[]string
```

</CodeBlocks>

### Example 3

<CodeBlocks>
```baml BAML
(int | float)[]
```
```python Python Equivalent
List[Union[int, float]]
```

```typescript TypeScript Equivalent
number[]
```

```go Go Equivalent
[]Union2IntOrFloat // Generated union type slice
```

</CodeBlocks>

### Example 4

<CodeBlocks>
```baml BAML
(int? | string[] | MyClass)[]
```

```python Python Equivalent
Optional[List[Union[Optional[int], List[str], MyClass]]]
```

```typescript TypeScript Equivalent
((number | null) | string[] | MyClass)[]
```

```go Go Equivalent
[]Union3IntOrStringArrayOrMyClass // Generated union type slice
```

</CodeBlocks>

### Example 5

<CodeBlocks>
```baml BAML
"str" | 1 | false
```

```python Python Equivalent
Union[Literal["str"], Literal[1], Literal[False]]
```

```typescript TypeScript Equivalent
"str" | 1 | false
```

```go Go Equivalent
Union3StringOrIntOrBool // Generated union type with literal validation
```

</CodeBlocks>

## ⚠️ Unsupported
- `any/json` - Not supported. We don't want to encourage its use as it defeats the purpose of having a type system. if you really need it, for now use `string` and call `json.parse` yourself or use [dynamic types](/guide/baml-advanced/dynamic-runtime-types)
- `datetime` - Not yet supported. Use a `string` instead.
- `duration` - Not yet supported. We recommend using `string` and specifying that it must be an "ISO8601 duration" in the description, which you can parse yourself into a duration.
- `units (currency, temperature)` - Not yet supported. Use a number (`int` or `float`) and have the unit be part of the variable name. For example, `temperature_fahrenheit` and `cost_usd` (see [@alias](/ref/baml/class))
